﻿using System;
using System.Collections.Generic;
using System.Linq;
using EzDesk.Message.Model;
using EzDesk.Utility;
using EzDesk.EzAppApi.Utility;

namespace EzDesk.Message.Service
{
    public class TopicService
    {
        #region [ 构造器 ]
        private EzApiClient apiClient;
        private EzDeskMessageDataContext _db;

        public TopicService(EzApiClient apiClient, EzDeskMessageDataContext db)
        {
            this.apiClient = apiClient;
            this._db = db;
        }

        public TopicService()
            : this(new EzApiClient(), new EzDeskMessageDataContext())
        {
        }
        #endregion


        /// <summary>
        /// 创建新的消息
        /// </summary>
        /// <returns>新消息的ID</returns>
        public Guid CreateNewTopic(Guid senderId, string msgText, bool isNeedConfirm, string memberString)
        {
            Guid topicId = Guid.NewGuid();
            ez_Message newMsg = new ez_Message()
            {
                MessageId = topicId,
                ParentId = topicId,
                CreateOn = DateTime.Now,
                SenderId = senderId,
                Text = msgText,
                NeedConfirm = isNeedConfirm,
                MemberString = memberString,
            };

            // 保存新的消息
            using (var db = new EzDeskMessageDataContext())
            {
                db.ez_Messages.InsertOnSubmit(newMsg);
                db.SubmitChanges();
            }


            // 发送各种通知

            // 发送对象总是要包括自己
            string updateFeedMemberString = EzDeskAppApiHelper.MemberStringHelper.JoinUserId(memberString, senderId);

            Guid feedId;
            Guid templateId;
            var targetUserList = apiClient.GetAllUsersByMemberString(memberString);

            if (!isNeedConfirm)
            {
                // 发送 不需要确认的消息 的 Update 通知
                templateId = new Guid("F6D4B462-5469-4BD0-BA63-82312646BB4B");
                IDictionary<string, string> feedData = new Dictionary<string, string>();
                feedData.Add("senderId", senderId.ToString());
                feedData.Add("senderName", apiClient.GetSimpleUserById(senderId).Name);
                feedData.Add("messageId", topicId.ToString());
                feedData.Add("messageText", msgText);
                feedData.Add("replyCount", "0");

                feedId = apiClient.SendFeed(
                    "update",
                    templateId,
                    senderId,
                    JsonHelper.ConvertToJson(feedData),
                    memberString,
                    true  
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";

                apiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );
            }
            else
            {
                // 发送 需要确认的消息 的 Update 通知
                templateId = new Guid("17B4D7C3-77F0-49B3-8F19-3BD9C0B8963B");
                IDictionary<string, string> feedData = new Dictionary<string, string>();
                feedData.Add("senderId", senderId.ToString());
                feedData.Add("senderName", apiClient.GetSimpleUserById(senderId).Name);
                feedData.Add("messageId", topicId.ToString());
                feedData.Add("messageText", msgText);
                feedData.Add("replyCount", "0");
                feedData.Add("confirmCount", "0");

                feedId = apiClient.SendFeed(
                    "update",
                    templateId,
                    senderId,
                    JsonHelper.ConvertToJson(feedData),
                    memberString,
                    true /* 不发送给自己 */
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";

                apiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );
            }

            // 在message本地保存发送出去的Feed信息
            using (var db = new EzDeskMessageDataContext())
            {
                foreach(var item in targetUserList)
                {
                    db.ez_MessageFeeds.InsertOnSubmit(
                        new ez_MessageFeed()
                        {
                            UserId = item.Id,
                            FeedId = feedId,
                            MessageId = topicId,
                            TemplateId = templateId
                        }
                        );
                }
                db.SubmitChanges();
            }

            
            if (isNeedConfirm)
            {
                // 发送要确认的Notification消息    

                Guid tempalteId = new Guid("68583F03-4530-434C-8349-05F66DA6817F");
                IDictionary<string, string> feedData = new Dictionary<string, string>();
                feedData.Add("senderId", senderId.ToString());
                feedData.Add("senderName", apiClient.GetSimpleUserById(senderId).Name);
                feedData.Add("messageId", topicId.ToString());
                feedData.Add("messageText", msgText);

                feedId = apiClient.SendFeed(
                    "notification",
                    tempalteId,
                    senderId,
                    JsonHelper.ConvertToJson(feedData),
                    memberString,
                    false /* 就不发给自己了 */
                    );

                targetUserList = apiClient.GetAllUsersByMemberString(memberString);

                // 在message本地保存发送出去的Feed Notificaiton
                using (var db = new EzDeskMessageDataContext())
                {
                    foreach (var item in targetUserList)
                    {
                        if (item.Id != senderId)
                        {
                            db.ez_MessageFeeds.InsertOnSubmit(
                                new ez_MessageFeed()
                                {
                                    UserId = item.Id,
                                    FeedId = feedId,
                                    MessageId = topicId,
                                    TemplateId = new Guid("68583F03-4530-434C-8349-05F66DA6817F"),
                                }
                                );
                        }
                    }
                    db.SubmitChanges();
                }
            }

            return topicId;
        }
        
        /// <summary>
        /// 回复一条消息
        /// </summary>
        /// <param name="senderId"></param>
        /// <param name="messageText"></param>
        /// <param name="memberString"></param>
        /// <param name="needConfirm"></param>
        public void ReplyToMessage(Guid senderId, Guid replyToMessageId, Guid topicId, string messageText, bool isReplyToAll)
        {
            // 找被回复的消息
            var replyToMessage = _db.ez_Messages.Where(p=>p.MessageId == replyToMessageId)
                .SingleOrDefault();
            if (replyToMessage == null)
            {
                //todo: 没找到要回复的消息
                throw new Exception("Message Not Found!");
            }

            // 找被回复的消息的主题
            ez_Message topicMessage = null;
            if (topicId != replyToMessageId)
            {
                topicMessage = _db.ez_Messages.Where(p => p.MessageId == topicId && p.MessageId == p.ParentId)
                    .SingleOrDefault();
                if (topicMessage == null)
                {
                    //todo: 没找到要回复的主题
                    throw new Exception("Topic Not Found!");
                }
            }
            else
            {
                topicMessage = replyToMessage;
            }


            using (var db = new EzDeskMessageDataContext())
            {
                // 验证memberstring
                Guid newMessageId = Guid.NewGuid();
                db.ez_Messages.InsertOnSubmit(
                    new ez_Message()
                    {
                        MessageId = newMessageId,
                        SenderId = senderId,
                        MemberString = topicMessage.MemberString,
                        ParentId = topicId,
                        CreateOn = DateTime.Now,
                        Text = messageText,
                        NeedConfirm = false,
                    }
                );
                db.SubmitChanges();
            }

            // 更新 回复数目
            topicMessage.ReplyCount++;
            _db.SubmitChanges();



            // 回复了消息 开始发送回复消息的通知

            // 给“楼主”和被回复人 发送一条Notificaiton
            string replyNotiMemberstring = null;
            if (isReplyToAll)
            {
                replyNotiMemberstring = topicMessage.MemberString;
            }
            else
            {
                replyNotiMemberstring = EzDeskAppApiHelper.MemberStringHelper.JoinUserId(replyNotiMemberstring, topicMessage.SenderId);
                replyNotiMemberstring = EzDeskAppApiHelper.MemberStringHelper.JoinUserId(replyNotiMemberstring, replyToMessage.SenderId);
            }


            Guid tempalteId = new Guid("ED03BACE-E2C1-4EFC-93B7-2D1DE347615A");
            IDictionary<string, string> feedData = new Dictionary<string, string>();
            feedData.Add("senderId", senderId.ToString());
            feedData.Add("senderName", apiClient.GetSimpleUserInfos(senderId.ToString())[0].Name);
            feedData.Add("messageId", topicId.ToString());
            feedData.Add("messageText", messageText);
            feedData.Add("messageTextSummary", new MessageContent(topicMessage.Text).SummrizedMessage);
            
            Guid feedId = apiClient.SendFeed(
                "notification",
                tempalteId,
                senderId,
                JsonHelper.ConvertToJson(feedData),
                replyNotiMemberstring,
                false
                );
            var targetUserList = apiClient.GetAllUsersByMemberString(replyNotiMemberstring);

            // 在message本地保存发送出去的Feed Notificaiton
            using (var db = new EzDeskMessageDataContext())
            {
                foreach (var item in targetUserList)
                {
                    if (item.Id != senderId)
                    {
                        db.ez_MessageFeeds.InsertOnSubmit(
                            new ez_MessageFeed()
                            {
                                UserId = item.Id,
                                FeedId = feedId,
                                MessageId = topicId,
                                TemplateId = new Guid("ED03BACE-E2C1-4EFC-93B7-2D1DE347615A"),
                            }
                            );
                    }
                }
                db.SubmitChanges();
            }


            // 更新消息 Update 的回复数目
            var sentFeed = _db.ez_MessageFeeds.Where(
                p => p.MessageId == topicId &&
                (p.TemplateId == new Guid("F6D4B462-5469-4BD0-BA63-82312646BB4B") ||
                p.TemplateId == new Guid("17B4D7C3-77F0-49B3-8F19-3BD9C0B8963B"))
                )
                .Select(p => p.FeedId)
                .Distinct()
                .SingleOrDefault();
            IDictionary<string, string> updateData = new Dictionary<string, string>();
            updateData.Add("replyCount", topicMessage.ReplyCount.ToString()); //更新的消息回复数目
            string updateDataStr = JsonHelper.ConvertToJson(updateData);

            apiClient.UpdateFeedData(sentFeed, updateDataStr);
        }

        /// <summary>
        /// 获得一个完整的主题
        /// </summary>
        /// <param name="topicId"></param>
        /// <returns></returns>
        public Topic GetFullTopic(Guid topicId, Guid actorUserId)
        {
            Topic topic = null;
            using (var db = new EzDeskMessageDataContext())
            {
                var innerTopic = db.ez_Messages.Where(p => p.MessageId == topicId).SingleOrDefault();

                if ((innerTopic == null) || (innerTopic.ParentId != innerTopic.MessageId))
                {
                    // todo: 没有找到合适的主题
                    throw new Exception("Topic Not Found!");
                }

                topic = new Topic()
                {
                    MessageId = innerTopic.MessageId,
                    CreateOn = innerTopic.CreateOn,
                    MessageText = innerTopic.Text,
                    Sender = apiClient.GetSimpleUserById(innerTopic.SenderId),
                    Recipient = apiClient.GetSimpleUserById(actorUserId),
                    NeedConfirm = innerTopic.NeedConfirm,
                    ConfirmedInfo = getConfirmdInfo(innerTopic),
                    ReplyList = getReplys(innerTopic),
                    Participator = getParticipatorInfo(innerTopic.MemberString),
                };
                
                // 如果有“回复通知”的Notification，则将他们全部取消(使之无效)
                // (看过消息了，就不用再提醒了)
                var notis = _db.ez_MessageFeeds.Where(p =>
                    p.MessageId == topicId &&
                    p.TemplateId == new Guid("ED03BACE-E2C1-4EFC-93B7-2D1DE347615A") &&
                    p.UserId == actorUserId
                    )
                    .Select(p => p.FeedId)
                    .ToList();

                string feedIdStrs = EzDeskAppApiHelper.MemberStringHelper.GetIdStrdFromIdList(notis);
                apiClient.SetFeedsIsAvailable(feedIdStrs, actorUserId.ToString(), false);                

            }
            return topic;
        }


        public SingleMessage GetSingleMessage(Guid messageId)
        {
            SingleMessage singleMessage = _db.ez_Messages.Where(p => p.MessageId == messageId)
                .Select(
                p => new SingleMessage()
                {
                    MessageId = p.MessageId,
                    MessageText = p.Text,
                    ParentMessageId = p.ParentId,
                    SenderId = p.SenderId,
                    CreateOn = p.CreateOn,
                }
                )
                .SingleOrDefault();

            if (singleMessage == null)
            {
                throw new Exception("Message Not Found!");
            }

            return singleMessage;
        }


        /// <summary>
        /// 确认一条消息
        /// </summary>
        /// <param name="messageId"></param>
        /// <param name="actorUser"></param>
        public void ConfirmMessage(Guid messageId, Guid actorUserId)
        {
            var message = _db.ez_Messages
                .Where(p => p.MessageId == messageId)
                .SingleOrDefault();

            if (message == null || !message.NeedConfirm)
            {
                // todo: error
                throw new Exception("没有找到需要确认的消息: " + messageId.ToString());
            }

            if (message.SenderId == actorUserId)
            {
                throw new Exception("您不需要确认自己的消息");
            }

            var members = apiClient.GetAllUsersByMemberString(message.MemberString);
            if (!members.ContainUser(actorUserId))
            {
                //todo: error
                throw new Exception("您没资格确认这个消息");
            }

            var messageConfirm = _db.ez_MessageConfirms
                .Where(p => p.MessageId == messageId && p.UserId == actorUserId)
                .SingleOrDefault();
            if (messageConfirm != null)
            {
                //todo: error
                throw new Exception("已经确认过了...");
            }


            // 添加确认实体
            var actor = apiClient.GetSimpleUserInfos(actorUserId.ToString())[0];
            ez_MessageConfirm msgConfirm = new ez_MessageConfirm()
            {
                MessageId = messageId,
                UserId = actorUserId,
                UserName = actor.UserName,
                ConfirmOn = DateTime.Now,
            };
            using (var db = new EzDeskMessageDataContext())
            {
                db.ez_MessageConfirms.InsertOnSubmit(
                    msgConfirm
                    );
                db.SubmitChanges();
            }

            // 更新 已确认 数目
            message.ConfirmCount ++;
            _db.SubmitChanges();
            

            // 更新消息Feed的 “已确认” 数据
            var feedDatas = _db.ez_MessageFeeds
                .Where(p=>p.MessageId == messageId && p.TemplateId == new Guid("17B4D7C3-77F0-49B3-8F19-3BD9C0B8963B"))
                .Select(p=>p.FeedId)
                .ToList();
            IDictionary<string, string> newFeedData =new Dictionary<string, string>();
            newFeedData.Add("confirmCount", message.ConfirmCount.ToString());
            var newFeedDataStr = JsonHelper.ConvertToJson(newFeedData);

            string feedIdStrs = EzDeskAppApiHelper.MemberStringHelper.GetIdStrdFromIdList(feedDatas);
            apiClient.UpdateFeedsData(feedIdStrs, newFeedDataStr);

            // 删除确认者收到的Notification
            using(var db = new EzDeskMessageDataContext())
            {
                var feeds = db.ez_MessageFeeds
                    .Where(p => p.MessageId == messageId && p.UserId == actorUserId && p.TemplateId == new Guid("68583F03-4530-434C-8349-05F66DA6817F"))
                    .Select(p=>p.FeedId)
                    .ToList();

                feedIdStrs = EzDeskAppApiHelper.MemberStringHelper.GetIdStrdFromIdList(feeds);
                apiClient.SetFeedsIsAvailable(feedIdStrs, actorUserId.ToString(), false);
            }
        }


        /// <summary>
        /// 获取一些消息,自动按Update时间排序
        /// </summary>
        /// <param name="recipienId">接收者ID</param>
        /// <param name="senderId">发送者Id</param>
        /// <param name="maxCount">消息最大条数</param>
        /// <returns></returns>
        public IList<SingleMessage> GetMessages(Guid? recipienId, Guid? senderId, int startIndex = 0, int maxCount = 5)
        {
            throw new NotImplementedException();
        }


        #region [ private methods ]
        /// <summary>
        /// 找出一个主题下面所有的回复
        /// </summary>
        /// <param name="innerTopic"></param>
        /// <returns></returns>
        private PagedList<SingleMessage> getReplys(ez_Message innerTopic)
        {
            PagedList<SingleMessage> pagedReplys;
            var replys = _db.ez_Messages.Where(p => p.ParentId == innerTopic.ParentId && p.MessageId != p.ParentId)
                .OrderBy(p => p.CreateOn)
                .Select(
                p => new SingleMessage()
                {
                    MessageId = p.MessageId,
                    MessageText = p.Text,
                    ParentMessageId = p.ParentId,
                    SenderId = p.SenderId,
                    CreateOn = p.CreateOn,
                }
                ).ToList();
            pagedReplys = new PagedList<SingleMessage>(replys, 0, 20);
            return pagedReplys;
        }

        /// <summary>
        /// 找出一个主题下面的所有确认信息
        /// </summary>
        /// <param name="innerTopic"></param>
        /// <returns></returns>
        private LazyList<MessageConfirm> getConfirmdInfo(ez_Message innerTopic)
        {
            if (!innerTopic.NeedConfirm)
            {
                return null;
            }
           
            var confirmedList = _db.ez_MessageConfirms.Where(p => p.MessageId == innerTopic.MessageId)
                .Select(p => new MessageConfirm()
                {
                    UserId = p.UserId,
                    ConfirmOn = p.ConfirmOn,
                }
                );

            return new LazyList<MessageConfirm>(confirmedList);
        }


        private ParticipatorsInfo getParticipatorInfo(string memberstring)
        {
            var participator = new ParticipatorsInfo()
            {
                Memberstring = memberstring,
                AllUserMemebers = EzDeskAppApiHelper.MemberStringHelper.GetAllUsersInMemberstring(memberstring),
                GroupParticipators = EzDeskAppApiHelper.MemberStringHelper.GetGroupsInMemberstring(memberstring),
                UserParticipators = EzDeskAppApiHelper.MemberStringHelper.GetUsersInMemberstring(memberstring),
            };
            return participator;
        }
        #endregion

    }
}
